﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using SalesSys.BLL;
using SalesSys.BLL.Purchasing;
using SalesSys.BLL.Sales;
using SalesSys.Comm.Utility;
using SalesSys.DAL.Models;
using SalesSys.BLL.Depot;
using OrderBLL = SalesSys.BLL.Sales.OrderBLL;

namespace SalesSys.Service.Sales
{



    public class SalesSvc : BaseBLL<Order, Guid>, IDirectSale
    {

        private IPurchasingBLL purchasingBll=new PurchasingBLL();
        private IOrderBLL orderBll=new SalesSys.BLL.Sales.OrderBLL();
       // private IDeliverySheetBLL deliverySheetBll;
        private EmployeeBLL employeeBll=new EmployeeBLL();



        /// <summary>
        /// 直发采购，通过订单创建采购单
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public IResultState CreateByOrder(Guid orderId,PurchaseOrder info)
        {
            //复制
            return null;
        }
        /// <summary>
        /// 采购确认接单
        /// </summary>
        /// <param name="createrId">接单人</param>
        /// <param name="orderId">订单</param>
        /// <returns></returns>
        /// <remarks>
        /// 1.验证
        /// 2.设置订单为已接单
        /// 3.创建采购单，并计算采购单各商品价格
        /// </remarks>
        public IResultState OrderPurchasingConfirm(Guid createrId, Guid orderId)
        {

            var order = orderBll.Details(orderId);
            var isOk = order != null && order.State == OrderState.Checked && order.Provider.MainFieldMan.Id == createrId;
            if (!isOk)
            {
                return ReState.ArgError.Create("参数错误");
            }
            using (var tran = new TransactionScope())
            {
                orderBll.SetState(createrId, order.Id, OrderState.Ordered);
                var re = purchasingBll.CreateBySale(createrId, order);
                tran.Complete();
                return ReState.Success.Create();
            }
        }


        /// <summary>
        /// 订单发货
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 验证订单状态必须为：已接单，发货人必须为采购
        /// 设置订单状态
        /// 生成发货单
        /// 设置订单状态：已发货
        /// </remarks>
        public IResultState OrderSend(Guid handlerId, Guid orderId)
        {
            var order = orderBll.Details(orderId);
            using (var tran = new TransactionScope())
            {
                var stockLockBll = new StockLockBLL();
                // DeliverySheet re = deliverySheetBll.CreateByOrder(order);
                if (order.Provider.ProviderType == ProviderType.Producer)
                    //核销锁库单
                    stockLockBll.WriteOffSheet(order);
                orderBll.SetState(handlerId, order.Id, OrderState.Send);

                if (order.OrderType == OrderType.Normal || (order.Provider.ProviderType == ProviderType.Producer && (order.OrderType == OrderType.BasePriceLock || order.OrderType == OrderType.ProductLock)))
                {
                    var pOrder = purchasingBll.GetPurchaseOrderByOrderId(order.Id);
                    if (pOrder == null)
                        return ReState.Error.Create("计划单相应采购单不存在");
                    if (pOrder.State != SalesSys.DAL.Models.PurchaseOrder.PurchaseState.Complete)
                        return ReState.Error.Create("对应采购单还未完成采购");
                    pOrder.State = SalesSys.DAL.Models.PurchaseOrder.PurchaseState.Send;
                    purchasingBll.Edit(pOrder);
                }
                tran.Complete();
                return ReState.Success.Create();
            }
        }
        /// <summary>
        /// 销售单生成出库单
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public IResultState ToDepotDelivery(Guid orderId,Guid empId)
        {
            var order = orderBll.Details(orderId);
            if (order.State!=OrderState.Send)
            {
                return ReState.ArgError.Create("状态错误");
            }
            //先进行核销锁库单操作，然后做实际发货量的减少
            var stockLockBll = new StockLockBLL();
            //核销锁库单
            stockLockBll.WriteOffSheet(order);
            orderBll.ToDepotDelivery(order,empId);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 结算
        /// </summary>
        /// <param name="handlerId"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 验证订单状态：已发货
        /// 重新计算订单金额
        /// 设置货款、运费
        /// 比较货款、运费，与实际支付差额
        /// 对差额进行入账
        /// 设置订单状态：已结算
        /// </remarks>
        public IResultState Settlement(Guid handlerId, Guid orderId)
        {

            var order = orderBll.Details(orderId);
            if (order == null || order.State != OrderState.Send || order.IsSettlement)
            {
                return ReState.ArgError.Create("参数错误");
            }
            var emp = employeeBll.Details(handlerId);
            //结算时如果没有先款，则不享受先款优惠
            if (order.IsFullPayment)
            {
                if (order.Prepayments < MoneyLocalizable.ToMoney(order.SourceTotal * OrderBLL.payments))
                {
                    order.UnitDiscount = 0;
                    order.UnitTotal = 0;
                    OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, emp, 0, "先款优惠失效！");
                }
                else
                {
                    order.UnitDiscount = order.Provider.FullPaymentDiscount;
                }
            }
            else
            {
                order.UnitDiscount = 0;
                order.UnitTotal = 0;
            }
            //非标优惠
            if (!order.IsStandard)
            {
                order.NonstandardDiscount = order.Provider.NonstandardDiscount;
                order.UnitDiscount += order.Provider.NonstandardDiscount;
            }
            OrderBLL.SetOrderChangeRecord(order, DiscountType.Msg, emp, 0, "开始结算");
            orderBll.Settlement(order,emp);

            return ReState.Success.Create();
        }


        /// <summary>
        /// 支付订单,分别对货款与运费支付，与预付款支付不同，应做区分
        /// </summary>
        /// <param name="handlerId"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 计算订单货款、运费，剩余金额
        /// 通过账户扣款支付
        /// 更新订单货款、运费，已支付
        /// </remarks>
        public IResultState PayOrder(Guid handlerId, Guid orderId)
        {
            using (var tran = new TransactionScope())
            {
                try
                {
                    var order = Details(orderId);
                    FinanceBLL fbll = new FinanceBLL();
                    var emp = employeeBll.Details(handlerId);
                    var payMoney = fbll.PaymentOrder(order, emp);
                    var payDeli = fbll.PaymentOrderDelivery(order, emp);
                    order.Prepayments += payMoney;
                    order.PaidDelivery += payDeli;
                    Edit(order);
                    tran.Complete();
                    return ReState.Success.Create();
                }
                catch (Exception ex)
                {
                    return ReState.Error.Create(ex.Message);
                }

            }
        }

        /// <summary>
        /// 支付预付款，用于处理审批后，非信誉客户预付款支付，支付成功后进入下一步
        /// </summary>
        /// <returns></returns>
        public IResultState PayAdvanceCharge(Guid orderId, Guid handlerId)
        {
            var emp = employeeBll.Details(handlerId);
           var re= orderBll.PayAdvanCharge(orderId);
            var order=orderBll.Details(orderId);
            if (re)
            {
                OrderBLL.SetOrderChangeRecord(order,DiscountType.StateChange, emp);
                orderBll.Edit(order);
            }
            return ReState.Success.Create();
        }
       

        /// <summary>
        /// 设置收货凭证
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="receiptNames">文件名</param>
        /// <returns></returns>
        public IResultState SetReceipt(Guid orderId, string[] receiptNames)
        {
            var list = receiptNames.Select(p => new OrderVoucher() {OrderId = orderId, FileName = p}).ToArray();
            var bll = new BaseBLL<OrderVoucher, Guid>();
            bll.Create(list);
            return ReState.Success.Create();
        }
        /// <summary>
        /// 获取凭证
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public IResultState<string[]> GetReceipt(Guid orderId)
        {
            var bll = new BaseBLL<OrderVoucher, Guid>();
            var list = bll.GetList(p => p.OrderId == orderId).Select(p=>p.FileName).ToArray();
            return ReState.Success.CreateResult("", list);
        }

        /// <summary>
        /// 编辑订单基本信息
        /// </summary>
        /// <param name="orderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 更新订单、发货单信息
        /// </remarks>
        public IResultState OrderBaseEdit(Order orderDto,IEmployee emp)
        {
            var old = orderBll.Details(orderDto.Id);
            old.Address = orderDto.Address;
            old.IsDelivery = orderDto.IsDelivery;
            old.IsFullPayment = orderDto.IsFullPayment;
            old.IsPublicDelivery = orderDto.IsPublicDelivery;
            old.IsLockPrice = orderDto.IsLockPrice;
            old.Remarks = orderDto.Remarks;
            old.DeliveryPrice = orderDto.DeliveryPrice;
            old.Contact = orderDto.Contact;
            old.ContactPhone = orderDto.ContactPhone;
            old.VehicleInfos = orderDto.VehicleInfos;
            BLL.Sales.OrderBLL.SetOrderChangeRecord(old, DiscountType.BaseInfo, emp);
            orderBll.Edit(old);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 编辑订单商品信息，会引起价格变动，对已结算订单引起退款或应收账款
        /// </summary>
        /// <param name="orderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 1.更新计划单实际商品信息
        /// 计算商品价格、运费
        /// 
        /// 已结算的重新结算
        /// </remarks>
        public IResultState CommodityInfoEdit(Order orderDto,IEmployee emp)
        {
            orderBll.CommodityInfoEdit(orderDto,emp);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 创建计划单
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        /// <remarks>
        /// 判断订单类型，
        /// 验证订单类型是否与供应商字段匹配
        /// 根据订单类型处理
        /// </remarks>
        public new IResultState Create(Order order)
        {
            try
            {
                if (!order.IsStandard)
                {
                    if (!order.Account.IsCash || !order.DeliveryAccount.IsCash)
                    {
                        return ReState.Error.Create("户头错误");
                    }
                }


                //验证商品数量不能为0，并判断商品数量不允许超过库存数量
                if (order.CommodityInfos.Count == 0)
                {
                    return ReState.Error.Create("商品数量不能为0");
                }
                ProviderBLL providerBll = new ProviderBLL();
                var pro = providerBll.Details(order.Provider.Id);

                switch (order.OrderType)
                {
                    case OrderType.Normal:
                        orderBll.DirectCreate(order);
                        break;
                    case OrderType.ProductLock:
                        orderBll.ProductLockCreate(order);
                        break;
                    case OrderType.BasePriceLock:
                        orderBll.BasePriceLockCreate(order);
                        break;
                    case OrderType.Freedom:
                        if (pro.ProviderType != ProviderType.Merchant)
                        {
                            return ReState.ArgError.Create("订单类型不匹配");
                        }
                        orderBll.FreedomCreate(order);
                        break;
                    case OrderType.Depot:
                        if (pro.ProviderType != ProviderType.Depot)
                        {
                            return ReState.ArgError.Create("订单类型不匹配");
                        }
                        orderBll.DepotCreate(order);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
                return ReState.Success.Create();

            }
            catch (Exception ex)
            {
                return ReState.Error.Create(ex.Message);
            }
        }

        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="empId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 验证取消人
        /// 取消
        /// </remarks>
        public IResultState Cancel(Guid orderId, Guid empId)
        {
            //var order = orderBll.Details(orderId);
            //if (order.Creater.Id != empId)
            //    return ReState.ArgError.Create("取消人员错误");
            orderBll.Cancel(orderId, empId);
            return ReState.Success.Create();
        }


        /// <summary>
        /// 设置一个订单的商品真实重量信息，影响销售、
        /// </summary>
       /// <param name="order"></param>
        /// <returns></returns>
        public IResultState RealWeight(Order orderDto,IEmployee emp)
        {
 
            var ord = orderDto;
            var order = Details(ord.Id);
            if (order.State!=OrderState.Send)
            {
                return ReState.ArgError.Create("状态错误");
            }
            var oldTotal = order.Total;
            if (order.State != OrderState.Send)
                return null;
            order.SendTime = ord.SendTime;
            order.DeliveryPrice = ord.DeliveryPrice;
            var oldCommds = order.CommodityInfos;
            foreach (var item in ord.CommodityInfos)
            {
                var oldCommd = oldCommds.FirstOrDefault(p => p.Id == item.Id);
                if (oldCommd == null)
                {
                    return ReState.ArgError.Create("无法找到的订单商品信息");
                }
                oldCommd.Weight = item.Weight;
                oldCommd.Price = item.Price;
                oldCommd.Count = item.Count;
            }
            order.CalcNew();
            order.CalcDelivery();
            BLL.Sales.OrderBLL.SetOrderChangeRecord(order, DiscountType.PriceChange, emp, order.Total);
            orderBll.Edit(order);
          
            return ReState.Success.Create();
            
        }
    }

    public interface IDirectSale:IBaseBLL<Order,Guid>
    {
      /// <summary>
        /// 采购确认接单
      /// </summary>
      /// <param name="createrId">接单人</param>
      /// <param name="orderId">订单</param>
      /// <returns></returns>
      /// <remarks>
      /// 1.验证
      /// 2.设置订单为已接单
      /// 3.创建采购单，并计算采购单各商品价格
      /// </remarks>
          IResultState OrderPurchasingConfirm(Guid createrId, Guid  orderId);
        /// <summary>
        /// 订单发货
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 验证订单状态必须为：已接单，发货人必须为采购
        /// 1.设置订单状态
        /// 2.生成发货单
        /// 3.设置订单状态：已发货
        /// </remarks>
        IResultState OrderSend(Guid handlerId,Guid orderId);
     
        /// <summary>
        /// 结算
        /// </summary>
        /// <param name="handlerId"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 验证订单状态：已发货
        /// 重新计算订单金额
        /// 设置货款、运费
        /// 比较货款、运费，与实际支付差额
        /// 对差额进行入账
        /// 设置订单状态：已结算
        /// </remarks>
        IResultState Settlement(Guid handlerId,Guid orderId);
        /// <summary>
        /// 支付订单
        /// </summary>
        /// <param name="handlerId"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IResultState PayOrder(Guid handlerId, Guid orderId);

        /// <summary>
        /// 设置一个订单的商品真实重量信息，影响销售、
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        IResultState RealWeight(Order ord, IEmployee employee);

        
        /// <summary>
        /// 设置收货凭证
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="receiptId"></param>
        /// <returns></returns>
        IResultState SetReceipt(Guid orderId, string[] receiptId);

        /// <summary>
        /// 获取凭证名称
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IResultState<string[]> GetReceipt(Guid orderId);
        /// <summary>
        /// 编辑订单基本信息
        /// </summary>
        /// <param name="orderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 更新订单、发货单信息
        /// </remarks>
        IResultState OrderBaseEdit(Order orderDto,IEmployee emp);
        /// <summary>
        /// 编辑订单商品信息，会引起价格变动，对已结算订单引起退款或应收账款
        /// </summary>
        /// <param name="orderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 1.更新计划单实际商品信息
        /// 计算商品价格、运费
 
        /// 已结算的重新结算
        /// </remarks>
        IResultState CommodityInfoEdit(Order orderDto,IEmployee emp);

        /// <summary>
        /// 创建订单
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        IResultState Create(Order order);

        /// <summary>
        /// 取消订单
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="empId">申请人</param>
        /// <returns></returns>
        /// <remarks>
        ///验证：订单状态为待确认、审核通过
        /// 取消
        /// </remarks>
        IResultState Cancel(Guid orderId,Guid empId);

        IResultState ToDepotDelivery(Guid orderId, Guid empId);

    }



}
